package client

import (
	"github.com/gophercloud/gophercloud"
	"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
	"github.com/sirupsen/logrus"
)

type InstanceFileOpts struct {
	// Type is the type of reboot to perform on the server.
	File    string `json:"file" required:"false"`
	Content string `json:"content" required:"false"`
	Url     string `json:"url" required:"false"`
	//CallbackUrl string `json:"callback_url" required:"false"`
}

// ToInstanceFile builds a body for the reboot request.
func (opts InstanceFileOpts) ToInstanceFile() (map[string]interface{}, error) {
	return gophercloud.BuildRequestBody(opts, "")
}

/*
	Reboot requests that a given server reboot.

	Two methods exist for rebooting a server:

	HardReboot (aka PowerCycle) starts the server instance by physically cutting
	power to the machine, or if a VM, terminating it at the hypervisor level.
	It's done. Caput. Full stop.
	Then, after a brief while, power is restored or the VM instance restarted.

	SoftReboot (aka OSReboot) simply tells the OS to restart under its own
	procedure.
	E.g., in Linux, asking it to enter runlevel 6, or executing
	"sudo shutdown -r now", or by asking Windows to rtart the machine.
*/
func PostInstanceFile(client *gophercloud.ServiceClient, id string, opts InstanceFileOpts) (r servers.ActionResult) {
	b, err := opts.ToInstanceFile()
	if err != nil {
		r.Err = err
		return
	}
	resp, err := client.Post(instanceFileURL(client, id), b, nil, nil)
	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
	return
}

func GetInstanceFile(client *gophercloud.ServiceClient, id string) (r servers.ActionResult) {
	//b, err := opts.ToInstanceFile()
	//if err != nil {
	//	r.Err = err
	//	return
	//}
	url := instanceFileURL(client, id)
	resp, err := client.Get(url, &r.Body, &gophercloud.RequestOpts{
		OkCodes: []int{200, 203},
	})
	logrus.Info(resp, err)
	if err != nil && err.Error() == "EOF" {
		err = nil
	}

	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
	return
}

func instanceFileURL(client *gophercloud.ServiceClient, id string) string {
	return client.ServiceURL("servers", id, "os-instance_file")
}

//func NewMetricsV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
//	return initClientOpts(client, eo, "metric")
//}
//
//func initClientOpts(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts, clientType string) (*gophercloud.ServiceClient, error) {
//	sc := new(gophercloud.ServiceClient)
//	eo.ApplyDefaults(clientType)
//	url, err := client.EndpointLocator(eo)
//	if err != nil {
//		return sc, err
//	}
//	sc.ProviderClient = client
//	sc.Endpoint = url
//	sc.Type = clientType
//	return sc, nil
//}

///以下函数为仿照volumeactions写的，不知道为什么volumeaction中没有关于重设云盘状态的
type VolumeResetStatusResult struct {
	gophercloud.Result
}

type VolumeResetStatusOptsBuilder interface {
	ToImageMetadataMap() (map[string]interface{}, error)
}

type VolumeResetStatusOpts struct {
	//Metadata map[string]string `json:"metadata"`
	Status          string `json:"status,omitempty"`
	AttachStatus    string `json:"attach_status,omitempty"`
	MigrationStatus string `json:"migration_status,omitempty"`
}

func (opts VolumeResetStatusOpts) ToImageMetadataMap() (map[string]interface{}, error) {
	return gophercloud.BuildRequestBody(opts, "os-reset_status")
}

func actionURL(c *gophercloud.ServiceClient, id string) string {
	return c.ServiceURL("volumes", id, "action")
}

func VolumeResetStatus(client *gophercloud.ServiceClient, id string, opts VolumeResetStatusOptsBuilder) (r VolumeResetStatusResult) {
	b, err := opts.ToImageMetadataMap()
	if err != nil {
		r.Err = err
		return
	}
	resp, err := client.Post(actionURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
		OkCodes: []int{202},
	})
	if err.Error() == "EOF" {
		err = nil
	}
	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
	return
}

///到此为此

/// 添加os-console-auth-tokens方法
func OSConsoleAuthTokens(client *gophercloud.ServiceClient, authtoken string) (r gophercloud.Result) {
	consoleurl := consoleTokenUrl(client, authtoken)
	resp, err := client.Get(consoleurl, &r.Body, &gophercloud.RequestOpts{
		OkCodes: []int{200},
	})

	//if err.Error() == "EOF" {
	//	err = nil
	//}
	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
	return
}

func consoleTokenUrl(c *gophercloud.ServiceClient, id string) string {
	return c.ServiceURL("os-console-auth-tokens", id)
}

type OSConsoleResultStruct struct {
	Console *OSConsoleResultStruct1 `json:"console"`
}
type OSConsoleResultStruct1 struct {
	InstanceUuid       string `json:"instance_uuid"`
	Host               string `json:"host"`
	Port               int    `json:"port"`
	InternalAccessPath string `json:"internal_access_path"`
}

//type OsConsoleResult struct {
//	gophercloud.Result
//}

//
